<?php
/**
 * Created by PhpStorm.
 * User: xiaomeng
 * Date: 17-9-14
 * Time: 下午3:39
 */

namespace swf\socket;

use swf\core\syncDb;

class OperaFd
{
    static private $allow_max_user_count = 5;
    static private $allow_type = ['user','observer'];
    /**
     * fd储存的格式:
     *         $online_list = [
                        1=>[
                        'userId'=>'10005',
                        'nickName'=>'小二',
                        'ico'=>'http://www.baidu.com',
                        'channelId'=>'000000000000000',
                        'roomId'=>5,
                        'type'=>'user'
                        ],
                        2=>[
                        'userId'=>'10006',
                        'nickName'=>'小三',
                        'ico'=>'http://www.baidu.com',
                        'channelId'=>'000000000000000',
                        'roomId'=>6,
     *                  'type'=>'user'
                        ],
                 ];
     *
     * 房间的格式：
                $channelid_000000000000000 = [
                    'room'=>[
                        1=>["users"=>[1,2,3,4,5],"observer"=>[6,7]],
                        2=>["users"=>[1,2,3,4,5],"observer"=>[6,7]],
                    ],
                    'other'=>'',
                ];
     *
     *
     */


    //保存fd在线 房间信息
    static public function save($fd,$userId = '',$nickName = '',$tel = '',$ico = '',$channelId = '000000000000000',$type = 'user')
    {
    //添加
        //用户类型判断
        if(!in_array($type,self::$allow_type))
        {
            return false;
        }
        //添加渠道
        $roomId = self::saveChannel($fd,$channelId,$type);
        if(is_null($roomId))
        {
            return false;
        }
        //添加fd
        $res = self::saveFd($fd,$userId,$nickName,$tel,$ico,$roomId,$channelId,$type);
        if(empty($res))
        {
            return false;
        }

        return true;



    }

    //创建房间
    static private function creatRoom($fd,$type)
    {
        $room_id = syncDb::redis()->incr('room_auto_id');

        //渠道data
        $data = [];
        //1.分配房间id
        if($type == 'user')
        {
            $data["user"][] = $fd;
            $data["observer"] = [];
        } else if($type == 'observer') {
            $data["user"] = [];
            $data["observer"][] = $fd;
        }
        $_data['room_id'] = $room_id;
        $_data['data'] = $data;
        return $_data;
    }
    //保存fd信息
    static private function saveFd($fd,$userId,$nickName,$tel,$ico,$roomId,$channelId,$type)
    {
        $res = syncDb::redis()->get('online_list');
        $res = json_decode($res,true);
        $res[$fd] = [
            'userId'=>$userId,
            'nickName'=>$nickName,
            'tel'=>$tel,
            'ico'=>$ico,
            'channelId'=>$channelId,
            'roomId'=>$roomId,
            'type'=>$type
        ];
        return syncDb::redis()->set('online_list',json_encode($res));
    }
    //保存渠道 返回房间id
    static private function saveChannel($fd,$channelId,$type)
    {
        //分配房间
        //获取渠道是否存在房间
        $channelData = syncDb::redis()->get('channelid_'.$channelId);
        $channelData = json_decode($channelData,true);
        $room_id = null;
        if(empty($channelData))
        {//不存在该渠道
            //1.分配房间id
            $data = self::creatRoom($fd,$type);
            $room_id = $data['room_id'];
            $_data['room'][$room_id] = $data['data'];//房间信息
            syncDb::redis()->set('channelid_'.$channelId,json_encode($_data));

        } else {//存在渠道
            $roomData = $channelData['room'];
            if($type == 'observer')
            {//直接添加到第一个
                $keys = array_keys($roomData);
                $room_id = $keys[0];
                $roomData[$room_id]['observer'][] = $fd;
                $channelData['room'] = $roomData;

            } else if($type == 'user'){
            //判断房间人数是否已满
                $lock = false;
                foreach ($roomData as $k=>$v)
                {
                    if(count($v['user']) < self::$allow_max_user_count)
                    {//添加到本房间
                        $room_id = $k;
                        $lock = true;
                        break;
                    }
                }
                if($lock === true)
                {//添加
                    $roomData[$room_id]['user'][] = $fd;
                    $channelData['room'] = $roomData;

                } else {//创建
                    $data = self::creatRoom($fd,$type);
                    $room_id = $data['room_id'];
                    $channelData['room'][$room_id] = $data['data'];//房间信息
                }

            }
            syncDb::redis()->set('channelid_'.$channelId,json_encode($channelData));

        }

        return $room_id;

    }

    //清空fd
    static public function clearFd($fd)
    {
        //1.清空用户fd
        $online_list = syncDb::redis()->get('online_list');
        $online_list = json_decode($online_list,true);
        $user_info = $online_list[$fd];
        unset($online_list[$fd]);
        syncDb::redis()->set('online_list',json_encode($online_list));
        //2.清空渠道信息

        $channelId = $user_info['channelId'];
        $userId = $user_info['userId'];
        $roomId = (int)$user_info['roomId'];
        $type = $user_info['type'];
        $channel_info = syncDb::redis()->get('channelid_'.$channelId);
        $channel_info = json_decode($channel_info,true);
        //清空用户ID
        self::clearUserId($userId);
        //存在的数组
        $key = array_search($fd, $channel_info['room'][$roomId][$type]);
        unset($channel_info['room'][$roomId][$type][$key]);

        syncDb::redis()->set('channelid_'.$channelId,json_encode($channel_info));
        return true;




    }

    //判断用户是否已经初始化
    static public function isInit($fd)
    {
        $online_list = syncDb::redis()->get('online_list');
        $online_list = json_decode($online_list,true);
        if(!isset($online_list[$fd]))
        {
            return false;//未初始化
        }
        return true;
    }

    /**
     * 获取房间其他人员fd
     * @param $fd
     */
    static public function getRoomFd($fd)
    {
        $user_info = self::getUserInfo($fd);
        $channelData = syncDb::redis()->get('channelid_'.$user_info['channelId']);
        $channelData = json_decode($channelData,true);
        $data['user'] = $channelData['room'][$user_info['roomId']]['user'];
        $data['observer'] = $channelData['room'][$user_info['roomId']]['observer'];
        return $data;
    }

    /**
     * 获取房间除自己外的其他人
     * @param $fd
     * @return array
     */
    static public function getRoomOtherFd($fd)
    {
        $fds = OperaFd::getRoomFd($fd);
        return  array_diff(array_merge($fds['user'],$fds['observer']),[$fd]);
    }

    /**
     * 获取用户信息
     * @param $fd
     * @return mixed
     */
    static public function getUserInfo($fd)
    {
        $online_list = syncDb::redis()->get('online_list');
        $online_list = json_decode($online_list,true);
        return $online_list[$fd];
    }

    /**
     * 获取用户fd
     * @param $userId
     */
    static public function getUserFd($userId)
    {
        $user_fds = syncDb::redis()->get('user_fds');
        $user_fds = json_decode($user_fds,true);
        return $user_fds[$userId];
    }

    /**
     * 设置用户id对应的fd
     * @param $userId
     * @param $fd
     * @return mixed
     */
    static public function setUserFd($userId,$fd)
    {
        $user_fds = syncDb::redis()->get('user_fds');
        $user_fds = json_decode($user_fds,true);
        $user_fds[$userId] = $fd;
        return syncDb::redis()->set('user_fds',json_encode($user_fds));
    }

    /**
     * 获取用户组信息
     * @param $fds
     * @return array
     */
    static public function getUsersInfo($fds)
    {

        $online_list = syncDb::redis()->get('online_list');
        $online_list = json_decode($online_list,true);
        $_data = [];
        foreach($fds as $k=>$fd)
        {
            $userInfo = $online_list[$fd];
            $_data[$k]['userId'] = $userInfo['userId'];
            $_data[$k]['nickName'] = $userInfo['nickName'];
            $_data[$k]['tel'] = $userInfo['tel'];
            $_data[$k]['ico'] = $userInfo['ico'];
        }
        return $_data;

    }

    /**
     * 获取渠道下所有房间的Fd信息
     * @param $channel_id
     * @return mixed
     */

    static public function getChannelFds($channel_id)
    {
        $channelData = syncDb::redis()->get('channelid_'.$channel_id);
        $channelData = json_decode($channelData,true);
        $fds = [];
        foreach($channelData['room'] as $k=>$v)
        {
            $fds = array_merge($fds,array_merge($v['user'],$v['observer']));
        }
        return $fds;

    }

    /**
     * 设置用户列表
     * @param $userId
     * @param $fd
     * @return bool
     */
    static public function setUserIdList($userId,$fd)
    {
        $userIdData = syncDb::redis()->get('user_id_list');
        $userIdData = json_decode($userIdData,true);
        if(isset($userIdData[$userId]))
        {
            return false;
        } else {
            $userIdData[$userId] = $fd;
            syncDb::redis()->set('user_id_list',json_encode($userIdData));
            return true;
        }
    }

    /**
     * 清楚用户userid
     * @param $userId
     * @return bool
     */
    static public function clearUserId($userId)
    {
        $userIdData = syncDb::redis()->get('user_id_list');
        $userIdData = json_decode($userIdData,true);
        unset($userIdData[$userId]);
        syncDb::redis()->set('user_id_list',json_encode($userIdData));
        return true;
    }

    /**
     * 获取用户房间用户信息
     * @param $roomId
     * @return mixed
     */
    static public function getRoomFdByRoomId($channelId,$roomId)
    {
        $channelData = syncDb::redis()->get('channelid_'.$channelId);
        $channelData = json_decode($channelData,true);
        $data['user'] = $channelData['room'][$roomId]['user'];
        $data['observer'] = $channelData['room'][$roomId]['observer'];
        return $data;
    }

    /**
     * 获取房间除自己外的其他人
     * @param $fd
     * @return array
     */
    static public function getRoomOtherFdByRoomId($channelId,$roomId,$fd)
    {
        $fds = OperaFd::getRoomFdByRoomId($channelId,$roomId);
        return  array_diff(array_merge($fds['user'],$fds['observer']),[$fd]);
    }

}